package com.zzl.study.auth.security.authentication;

import lombok.Data;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author: zhangzl
 * @date: 2024/3/12 21:07
 * @version: 1.0
 * @description: 自定义认证结果
 */
@Data
public class CustomAuthentication implements Transfer<UsernamePasswordAuthenticationToken> {

    /**
     * 自定义授权信息集合
     */
    private Collection<CustomAuthority> authorities;

    /**
     * 自定义Web端认证详情
     */
    private CustomWebAuthenticationDetails details;

    /**
     * 是否已认证
     */
    private boolean authenticated = false;

    /**
     * 自定义认证主体
     */
    private CustomPrincipal principal;

    /**
     * 认证凭证
     */
    private Object credentials;

    @Override
    public UsernamePasswordAuthenticationToken transform() {
        Set<GrantedAuthority> transformAuthorities = this.authorities == null ? new HashSet<>() : this.authorities.stream().map(CustomAuthority::transform).collect(Collectors.toSet());
        User transformPrincipal = this.principal == null ? null : this.principal.transform();
        WebAuthenticationDetails transformDetails = this.details == null ? null : this.details.transform();
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(transformPrincipal, this.credentials, transformAuthorities);
        token.setDetails(transformDetails);
        return token;
    }

    /**
     * 由Security框架中的认证结果转换为自定义认证结果
     *
     * @param usernamePasswordAuthenticationToken Security框架中的认证结果
     * @return 自定义认证结果
     */
    public static CustomAuthentication reTransform(UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) {
        if (usernamePasswordAuthenticationToken == null) {
            return null;
        }
        Set<CustomAuthority> transformAuthorities = usernamePasswordAuthenticationToken.getAuthorities() == null ? new HashSet<>() : usernamePasswordAuthenticationToken.getAuthorities().stream().map(authority -> {
            CustomAuthority customAuthority = new CustomAuthority();
            customAuthority.setRole(authority.getAuthority());
            return customAuthority;
        }).collect(Collectors.toSet());
        CustomPrincipal customPrincipal = CustomPrincipal.reTransform((User) usernamePasswordAuthenticationToken.getPrincipal());
        CustomWebAuthenticationDetails customWebAuthenticationDetails = CustomWebAuthenticationDetails.reTransform((WebAuthenticationDetails) usernamePasswordAuthenticationToken.getDetails());
        CustomAuthentication customAuthentication = new CustomAuthentication();
        customAuthentication.setAuthorities(transformAuthorities);
        customAuthentication.setDetails(customWebAuthenticationDetails);
        customAuthentication.setAuthenticated(usernamePasswordAuthenticationToken.isAuthenticated());
        customAuthentication.setPrincipal(customPrincipal);
        customAuthentication.setCredentials(usernamePasswordAuthenticationToken.getCredentials());
        return customAuthentication;
    }

}
